r'''

	Der TCP/IP Client

'''

import socket
import json
import serverinfo
import DiffieHellman
import xtea

class DHClient():
    '''
        Die Klasse ``DHClient`` stellt einen Client, der Daten mit einem Server austuascht, zur Verfuegung.
    '''
    def setup(self):
        '''
            Funktion stellt der Klasse verschiedene Objekte zur Verfuegung. Des Weiteren wird ein Socket angelegt,
            der sowohl Nachrichten an den Server schicken, als auch empfangen kann. Die empfangenen Nachrichten 
            werden in den folgenden Funktionen verarbeitet.         
            
            * ``dhobj`` realisiert das Diffie-Hellman-Protokoll
            * ``xtea_obj`` relasiert die Verschluesselung der Daten durch den XTEA-Algorithmus
            * Die Parameter ``HOST`` und ``PORT`` werden aus der Datei :py:mod:`serverinfo` gelesen.   
        '''
        self.HOST = serverinfo.HOST
        self.PORT = serverinfo.PORT
        self.dhobj = DiffieHellman.DHCrypt()
        self.xtea_obj = xtea.XTEA()
        self.confirm_msg = None
        
        try:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.sock.connect((self.HOST, self.PORT))
            self.connected = True
        except socket.error:
            self.connected = False
        
    def sendMsg(self, data):
        '''
            Die Funktion ``sendMsg()`` sendet die Nachrichten an den Server. Sollte das Senden fehlschlagen, wird 
            eine Exception ``socket.error`` geworfen.
        '''
        try:
            self.sock.send(data)   
            self.connected = True 
        except socket.error:
            self.connected = False
    
    def recieveMsg(self):
        '''
            Die Funktion ``recieveMsg()`` empfaengt Nachrichten vom Server. Es gibt nur zwei Arten von Nachrichten:
            
            1.    Der ``Handshake2``, in dem der Server seinen Schluessel mitteilt. Aus diesem Schluessel generiert
                  der Client seinen Schluessel, sodass beide den gleichen Wert zum Ver- und Entschluesseln der 
                  Nachrichten besitzen.
                  
            2.    Ein ``Confirm``, mit dem der Server den Erhalt der Nachricht quittiert.
        '''
        server_response = self.sock.recv(1024)
        (key,value) = self.parseInput(server_response)
        if key == "Handshake2":
            self.dhobj.genCommonKey(value)
        if key == "Confirm":
            self.confirm_msg = self.dhobj.xteaDecode(value)
            #self.confirm_msg = self.xtea_obj.strdecode(self.dhobj.key, value)
        return server_response
    
    def JSON_Handshake(self):
        '''
            Geniert die Handshake von Clientseite aus und gibt einen String im JSON Format zurueck.
        '''
        jobj = json.dumps({"Handshake1": self.dhobj.handSchack()})
        return jobj
    
    def JSON_Message(self, plaintext):
        '''
            Die Funktion nimmt die Nachricht als Klartext entgegen und verschluesselt sie mit Hilfe des
            XTEA Algorithmus und gibt das erstellte JSON-String zurueck.
        '''
        jobj = json.dumps({"Message": self.dhobj.xteaEncode(plaintext)})
        return jobj
    
    def parseInput(self,data):
        '''
            Die Funktion parst die Nachricht des Servers und gibt als Ergebnis
            die Parameter ``key`` und ``value``
            zueruck (Dictionary).
        '''
        key = None
        value = None
        job = json.loads(data)
        value = job.get("Handshake2")
        if(value is None): # wenn kein HS2: dann ist COnfirm !!! Do it later
            value = job.get("Confirm")
            if not(value is None): # also hier ist ein message -> entschluesselt es 
                key = "Confirm" # return nur roh daten, hier passiert keine Datenverabrbeitung
                return(key,value)
            else: # ungultig faelle
                pass
        else:# HS1 ist in value
            key = "Handshake2"
            return (key,value)
            pass
    
if __name__ == "__main__": 
    d = DHClient()
    d.setup()
    
    
    if d.connected:
        print "Handshake 1 gesendet"        
        z = d.JSON_Handshake()
        d.sendMsg(z)
        print "Done..."
        
        print "Handshake 2 von Server erhalten"
        r = d.recieveMsg()
        print "erhaltener Handshake 2... " + r
        print "Done..."
        
        print "Sende Nachricht an Server"
        y = d.JSON_Message('ABCDEFGH')
        d.sendMsg(y)
        print "Done..."
        
        print "Nachricht von Server"        
        s = d.recieveMsg()
        print "erhaltener Confirm " + s
        print "Confirm entschluesselt " + d.confirm_msg 
        print "Done..."
        
        print "Sende zweite Nachricht an Server"
        y = d.JSON_Message('IJKLMNOP')
        d.sendMsg(y)
        print "Done..."
        
        print "zweite Nachricht von Server"        
        s = d.recieveMsg()
        print "erhaltener Confirm " + s
        print "Confirm entschluesselt " + d.confirm_msg 
        print "Done..."
         
         
        

       
        
